from scapy.all import *
from comm import Comm
'''
d = 2
def region_growing(rulebound,sign,maxcost):
    p = []
    ibound = {}
    samplecount = 0
    samplesign = sign
    while samplesign*sign > 0 and samplecount < maxcost:
        pkt = select_core()
        samplecount = samplecount+1
        comm.inject_pkt(pkt)
        samplesign = comm.sign_of_last_pkt()
    if samplecount >maxcost:
        return p
    dimension = getpktdimension(pkt)
    imax = findmaxbound(pkt,dimension) 
    imin = findminbound(pkt,dimension)
    for i in range(0,len(imax)):
        ibound[dimension[i]] = (imin[i],imax[i])
    p.append((ibound,-sign))
    if samplecount < maxcost:
        leftcost = (maxcost -samplecount)/(2*len(dimension)+1) 
        p.append(region_growing(ibound,-sign,leftcost))
        otherbound1["ipv4"][1] = ibound["ipv4"][0]
        otherbound2["ipv4"][0] = rulebound["ipv4"][0]
        ob1[]
        p.append(region_growing(otherbound,sign,leftcost))
 '''
 comm = Comm()

 def region_growing(rulebound,sign,maxcost,**kwargs):
    p = []
    samplecount = 0
    samplesign = sign
    ibound  = []
    while samplesign == sign  and samplecount < maxcost:
        point = select_core(rulebound)
        samplecount = samplecount+1
        pktargs = point.copy()
        pktargs.update(kwargs)
        #pkt = comm.gen_pkt(pktargs)
        samplesign = comm.inject(pktargs)
        #samplesign = comm.sign_of_last_pkt()
    if samplecount >maxcost:
        return p
    ibound.append(findbound(rulebound[0],samplesign,pktargs,"dst_ip"))
    ibound.append(findportbound(rulebound[1],samplesign,pktargs,"tos"))
    p.append((ibound,samplesign))
    if samplecount <maxcost:
        leftcost = (maxcost - samplecount)/5
        p.append(region_growing(ibound,samplesign,maxcost))
        ob1 = [(rulebound[0][0],ibound[0][1]),(rulebound[1][0],rulebound[1][1])]
        ob2 = [(ibound[0][0],ibound[0][1]),(ibound[1][1],rulebound[1][1])]
        ob3 = [(ibound[0][1],rulebound[0][1]),(rulebound[1][0],rulebound[1][1])]
        ob4 = [(ibound[0][0],ibound[0][1]),(rulebound[1][0],ibound[1][0])]
        p = p + region_growing(ob1,sign,leftcost)
        p = p + region_growing(ob2,sign,leftcost)
        p = p + region_growing(ob3,sign,leftcost)
        p = p + region_growing(ob4,sign,leftcost)

    return p

def select_core(rulebound):
    # center
    core = {"dst_ip": (rulebound[0][0]+rulebound[0][1])/2,"tos":(rulebound[1][0]+rulebound[1][1])/2}
    return core

def findbound(bound,sign,pktargs,key):
    #high bound
    jump = 2
    jumpsign = sign
    lastjump = 0
    while pktargs[key]+jump < bound[1]:
        jumpargs = pktargs.copy()
        jumpargs[key] = jumpargs[key]+jump
        jumpsign = comm.inject(jumpargs)
        if jumpsign != sign:
            break
        lastjump = jump
        jump = jump *2
    if jumpsign != sign:
        highbound = binarysearch(lastjump, jump,pktargs,key,1)
    #low bound
    jump = 2
    jumpsign = sign
    lastjump = 0
    while pktargs[key] - jump > rulebound[0]:
        jumpargs = pktargs.copy()
        jumpargs[key] = jumpargs[key]-jump
        jumpsign = comm.inject(jumpargs)
        if jumpsign != sign:
            break
        lastjump = jump
        jump = jump *2
    if jumpsign != sign:
        lowbound = binarysearch(lastjump, jump,pktargs,key,sign,-1) 
    return (lowbound, highbound)

def binarysearch(low,high,pktargs,key,sign,x):
    while(low < high):
        mid = low+(high-low)/2
        jumpargs = pktargs.copy()
        if x<0:
            incre = -mid
        jumpargs[key] = jumpargs[key] + incre
        if comm.inject(jumpargs) != sign:
            high = mid -1
        else:
            low = mid +1
    return low    
  